﻿// SpriteCutter (tool for cutting single sprites from spritesheets)
// Copyright (C) 2009  D. Kostyreff a.k.a Nemezis
// 
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.


using System;
using System.Drawing;
using System.IO;

namespace SpriteCutter
{
	
	public class sprcut
	{
		static Bitmap pic;
		static bool changetotrans;
		public static void Main(string [] args)
		{
			unsafe
			{
			
			if (args.Length == 0 || args.Length < 4)
			{
				if (args.Length < 4)
					Console.WriteLine("incorrect number of arguments specified");
				Console.WriteLine("args: filename, sprite width, sprite height, \n change background color to transparent (true or false)");
				Console.WriteLine("example: 'simple.png 100 100 true'");
				Console.WriteLine("SpriteCutter by Nemezis, license: GPL v. 3.0");
				return;
			}
			
			if (File.Exists(args[0]) == false)
			{
				Console.WriteLine("File not found");
				
				return;
			}
			
			
			if (Convert.ToInt32(args[1]) < 0)
			{
				Console.WriteLine("x < 0"); 
				return;
			}
				
			if (Convert.ToInt32(args[2]) < 0)
			{
				Console.WriteLine("y < 0"); 
				return;
			}
			if (args[3] == "")
			{
				Console.WriteLine("true or false not found");
				return;
			}
			else
				if (args[3] == "true")
			   changetotrans = true;
			else
				if (args[3] == "false")
				changetotrans = false;
			else
			{
				Console.WriteLine("incorrect argument specified - "+args[3]);
				return;
			}
			
			pic = new Bitmap(args[0]);
			
			int tx = pic.Width; //total width of a pic
			int ty = pic.Height; //~~~ height
			int mx = Convert.ToInt32(args[1]); //max x of a cutted sprite
		    int my = Convert.ToInt32(args[2]); //max y ~~~~~
			Console.WriteLine("File loaded ok"); 
		    //finding background color in (0,0)
		    Color back = new Color();
		    back = pic.GetPixel(0,0);
		    
			
			//first we searching for top border of sprite line by moving on y and scanning x`es
			bool notempty = false;
			bool stillfilled = false;
			int [] topborder = new int [0];
			for (int y=0; y < ty; y++)
			{
				for (int x=0; x < tx; x++)
				{
					if (pic.GetPixel(x,y) != back)
					{
						notempty = true;
						break;
					}
					else 
					notempty = false;
				}
				if (notempty == true)
				{
					if (stillfilled == false)
				      {
					   
						topborder = (int[])IncreaseArray(topborder,topborder.Length+1);
						topborder[topborder.Length-1] = y;
					    stillfilled = true;
				      }	
				}
				else
				stillfilled = false;
				
			}
			
			Console.WriteLine("Top vertical bounds found : ");
			for (int i = 0; i < topborder.Length; i++)
			{
				Console.Write(topborder[i].ToString()+" ");
				
			}
			Console.WriteLine();
				
			//finding horizontal bounds, by moving on x and scaning y`es
			int [] leftborder = new int[0];
			int ymax;
			for (int i = 0; i<topborder.Length; i++)
			{
				notempty = false;
			    stillfilled = false;
			    if (i == topborder.Length-1)
	            ymax = pic.Height;
			    else
			    ymax= my + topborder[i];
			    
			for (int x = 0; x<tx; x++)
			{
				for (int y = topborder[i]; y<ymax; y++)
				{
					if (pic.GetPixel(x,y) != back)
					{
						notempty = true;
						break;
					}
					else
						notempty = false;
				}
				if (notempty == true)
				{
				if (stillfilled == false)
				   {
					   
				        leftborder = (int[])IncreaseArray(leftborder,leftborder.Length+1);
						leftborder[leftborder.Length-1] = x;
					    stillfilled = true;
				    }
				}
				else
				stillfilled = false;
			}
			}
			
		   Console.WriteLine("Left horizontal bounds found : ");
			for (int i = 0; i < leftborder.Length; i++)
			{
				if (i != leftborder.Length - 1)
				if (leftborder[i] > leftborder[i+1])
					Console.WriteLine();
					Console.Write(leftborder[i].ToString()+" ");
				
			}
			Console.WriteLine();
			
			//now we cutting images by moving to down-left border of image...
			//and changing BACKGROUND color to Transparent
			// 255,255,255, transparency alpha = 0
			
			Bitmap sprite;
			
			
			int xmax;
			
			int spritex = 0;
			int spritey = 0;
			int preva = 0;
			int filenum = 0;
			string dir = "Cutted from "+args[0].Replace('.','-');
			Directory.CreateDirectory(dir);
			
			for (int i = 0; i < topborder.Length; i++) //moving up - down
			{
				for (int a = preva; a < leftborder.Length; a++) //moving left - right
				{
					
					if (a == leftborder.Length - 1 || leftborder[a+1] < leftborder[a])
					{
						if ((pic.Width - leftborder[a]) >= mx)
							xmax = leftborder[a]+mx;
						else
							xmax = pic.Width;
					}
					else
					{
					if ((leftborder[a+1] - leftborder[a]) >= mx)
					xmax = leftborder[a] + mx;
					else
					xmax = leftborder[a] + (leftborder[a+1] - leftborder[a]);
					}
					
					if (i == topborder.Length - 1)
					{
						if ((pic.Height-topborder[i]) >= my)
						ymax = topborder[i] + my;
					else
					    ymax = pic.Height;
					}
					else
						ymax = topborder[i] + my;
					
					sprite = new Bitmap(mx,my);
					spritex = 0;
					spritey = 0;
					for (int x = leftborder[a]; x < xmax; x++)
					{
						spritey = 0;
						for (int y = topborder[i]; y < ymax; y++)
						{
							if (pic.GetPixel(x,y) == back)
							{
								if (changetotrans == true)
								sprite.SetPixel(spritex,spritey,Color.Transparent);
							    else
							    sprite.SetPixel(spritex,spritey,back);
							}
							else
								sprite.SetPixel(spritex,spritey,pic.GetPixel(x,y));
							spritey++;
							
						}
						spritex++;
					}
					
					Console.WriteLine("Sprite #"+(filenum+1).ToString()+" cuted and saved");
					sprite.Save(dir+"\\"+"filename"+(filenum+1).ToString()+".png");
					
					filenum++;
					if (a != leftborder.Length - 1)
					if (leftborder[a+1] < leftborder[a])
					{
						preva = a+1;
						break;
					}
				}
				
			}
			Console.WriteLine("all spite cuted and saved, press any key...");
			Console.ReadKey();
			}
			}
			     
			
			
		
		
		static Array IncreaseArray(Array array, int newLength)
        {
           Array newArray = Array.CreateInstance(array.GetType().GetElementType(), newLength);
           array.CopyTo(newArray, 0);
           return newArray;
        }

		
		
	}
}
